<template>
  <v-container class="page">
    <v-main class="page">
      <div class="page canvas-container">
        <canvas
          id="screen"
          :width="screenInfo.width"
          :height="screenInfo.height"
          @mousemove="move"
          @mousedown="mouseDown"
          @mouseup="mouseUp"
        ></canvas>
        <v-icon title="Toggle Menu" class="menuicon" @click="show = !show" >{{ icons.mdiMenu }}</v-icon>
      </div>
    </v-main>
    <Drawer :show="show" @change="updateProperties" />
    <v-snackbar
      v-model="snackbar"
    >
      {{tips}}
      <template v-slot:action="{ attrs }">
        <v-btn
          color="pink"
          text
          v-bind="attrs"
          @click="snackbar = false"
        >
          Close
        </v-btn>
      </template>
    </v-snackbar>
  </v-container>
</template>

<script>
import Drawer from './Drawer'
import {
  mdiMenu
} from '@mdi/js'
export default {
  name: 'Home',

  components: {
    Drawer
  },
  data () {
    return {
      show: false, // show Drawer
      url: null, // websocket url
      ws: null, // websocket connect
      connected: false, // is connect
      snackbar: false, // show tips
      tips: null, // tips message
      screen: null, // screen
      point: {
        x: 0,
        y: 0
      },
      isMouseDown: false,
      icons: { // icons
        mdiMenu
      },
      screenInfo: {
        width: 454,
        height: 454
      }
    }
  },
  methods: {
    mouseDown: function (e) {
      this.isMouseDown = true
      const point = {
        x: e.layerX,
        y: e.layerY
      }
      this.ws.send(JSON.stringify({
        version: '1.0.0',
        name: 'previewer',
        command: 'MousePress',
        args: point
      }))
    },
    move: function (e) {
      if (!this.isMouseDown) {
        return
      }
      this.point = {
        x: e.layerX,
        y: e.layerY
      }
      this.ws.send(JSON.stringify({
        version: '1.0.0',
        name: 'previewer',
        command: 'MouseMove',
        args: this.point
      }))
    },
    mouseUp: function (e) {
      this.isMouseDown = false
      const point = {
        x: e.layerX,
        y: e.layerY
      }
      this.ws.send(JSON.stringify({
        version: '1.0.0',
        name: 'previewer',
        command: 'MouseRelease',
        args: point
      }))
    },
    showTips: function (msg) {
      this.snackbar = true
      this.tips = msg
    },
    open: function () {
      console.log('connected')
      this.connected = true
      this.showTips('connected')
    },
    onmessage: function (evt) {
      if (evt.data instanceof Blob) {
        this.updateScreen(evt.data)
        return
      }
      console.log('receive:', evt)
      const msg = JSON.parse(evt.data)
      switch (msg.command) {
        case 'screeninfo':
          this.setScreenInfo(msg.args)
        default:
          console.log('unknow:', msg)
      }
    },
    close: function (e) {
      console.log('close:', e)
      this.connected = false
    },
    sendClose: function () {
      this.ws.close()
    },
    timer: function () {
      if (!this.connected) {
        this.initWS()
      }
    },
    initWS: function () {
      console.log('init ws')
      this.ws = new WebSocket(this.url)
      this.ws.onopen = this.open
      this.ws.onmessage = this.onmessage
      this.ws.onclose = this.close
      this.ws.onerror = this.close
    },
    updateProperties: function (values) {
      this.ws.send(JSON.stringify({
        version: '1.0.0',
        name: 'previewer',
        command: 'updateProperties',
        args: values
      }))
    },
    initScreen: function () {
      const node = document.getElementById('screen')
      this.screen = node.getContext('2d')
    },
    updateScreen: function (image) {
      const { width, height } = this.screenInfo
      const reader = new FileReader()
      reader.onload = (evt) => {
        if (evt.target.readyState === FileReader.DONE) {
          const data = evt.target.result
          const dv = new DataView(data)
          this.screen.clearRect(0, 0, width, height)
          let imgData = this.screen.createImageData(width, height)
          for (let i = 0; i < evt.total; i += 4) {
            imgData.data[i] = dv.getUint8(i + 1) // r
            imgData.data[i + 1] = dv.getUint8(i + 2) // g
            imgData.data[i + 2] = dv.getUint8(i + 3) // b
            imgData.data[i + 3] = dv.getUint8(i) // a
          }
          this.screen.putImageData(imgData, 0, 0)
        }
      }
      reader.readAsArrayBuffer(image)
    },
    setScreenInfo: function (data) {
      const { width, height } = data
      this.screenInfo = {
        width,
        height
      }
    }
  },
  created () {
    const loc = window.location
    let uri = 'ws:'
    if (loc.protocol === 'https:') {
      uri = 'wss:'
    }
    uri += '//' + loc.host
    this.url = uri
    if (process.env.NODE_ENV === 'development') {
      this.url = 'ws://localhost:4096/'
    }
  },
  mounted () {
    // connect websocket
    this.initWS()
    // init canvas
    this.initScreen()
    // close ws when page close
    window.οnbefοreunlοad = this.sendClose
    // auto reconnect ws
    setInterval(this.timer, 10 * 1000)
  }
}
</script>

<style scoped lang="less">
  .page {
    height: 100%;
    width: 100%;
    .canvas-container {
      display: flex;
      justify-content: center;
      align-items: center;
    }
    .screen {
    }
    .geo {
      padding-left: 0;
    }
    .no-left-padding {
      padding-left: 0;
    }
    .menuicon {
      position: fixed;
      bottom: 10px;
      right: 20px;
      z-index: 100;
    }
  }
</style>
